package algoritmos2011;

import algoritmos2011.NodoABB;

import algoritmos2011.Sistema.TipoRet;;




public class Red {
	//public static final int ACEPTAR=1;
	//public static final int RECHAZAR=2;

	enum RespuestaAmistad{ACEPTAR,RECHAZAR};
	enum RespuestaEvento{ASISTIRE,NOASISTIRE};
	private ArbolUsuario usuarios;

	//public enum TipoRet{OK, ERROR, NO_IMPLEMENTADA}



	//	Singleton ----------------------------------------

	//private static Red instancia = new Red();//estaba mal
	//private static Red instancia;
	public Red(){//no construia el arbol de usuarios

		this.usuarios=new ArbolUsuario();
	}

	/*public static Red getInstancia() {
		if (instancia==null){
			instancia=new Red();
		}
		return instancia;
	}*/

	//	------------------------------------------------

	//PRE 
	//POS 

	TipoRet responderEvento(String usuarioID, RespuestaEvento resp){
		Usuario usu=buscarUsuario(usuarioID,this.usuarios.getRaiz());
		if ((usu!=null)&&(usu.getEstado()==1)){		
			if (resp.equals(RespuestaEvento.ASISTIRE)){
				if(!usu.getInvitacionesEventos().esVacia()){
					NodoListaInvitacionesEventos aux=usu.getInvitacionesEventos().getInicio();
					usu.getInvitacionesEventos().setInicio(aux.getSig());
					usu.setCantEventosPend(usu.getCantEventosPend()-1);
					Usuario usuO=buscarUsuario(aux.getUsr(), usuarios.getRaiz());
					if(usuO.getEstado()==1){
						return enviarMensaje(usuarioID, aux.getUsr(), "Han aceptado su invitacion", "El usuario "+ usuarioID +" concurrira al evento"+ aux.getNombreEvento());
					}				
				}else{
					System.out.println("No hay invitaciones pendientes");
				}
			}else{				
				usu.getInvitacionesEventos().setInicio(usu.getInvitacionesEventos().getInicio().getSig());
				return TipoRet.OK;
			}	
		}else{
			System.out.println("El usuario "+ usuarioID  +" no existe");
		}			
		return TipoRet.ERROR;
	}

	// PRE 
	// POS 



	//=====================USUARIOS=====================



	public void setUsuarios(ArbolUsuario usuarios) {
		this.usuarios = usuarios;
	}

	public ArbolUsuario getUsuarios() {
		return usuarios;
	}

	public TipoRet mostrarUSuarios(){
		if(!usuarios.esVacio()){
			mostrarUsuarios(usuarios.getRaiz());	
		}else{
			System.out.println(" No hay usuarios creados");	
		}
		return TipoRet.OK;
	}

	private void mostrarUsuarios(NodoABB abb){
		if (!(abb==null)){
			mostrarUsuarios(abb.getIzq());

			System.out.println(abb.getUsuario().getUsuarioID()+ " :  " + abb.getUsuario().verEstado()+
					"\n" + "Cantidad de amigos: "+ abb.getUsuario().getCantAmigos()+ 
					"\n" + "Cantidad de mensajes recibidos: " + abb.getUsuario().getCantMensajesRec()	+ 
					"\n" + "Cantidad de mensajes enviados: " + abb.getUsuario().getCantMensajesEnv()+
					"\n" + "Cantidad de solicitudes pendientes: " + abb.getUsuario().getCantSolicitudesPend()+
					"\n" + "Cantidad de eventos pendientes: " + abb.getUsuario().getCantEventosPend()); 
			mostrarUsuarios(abb.getDer());
		}


	}
	public void agregarUsuario (Usuario user){
		if (!usuarios.esVacio())
			usuarios.setRaiz(agregarUsuario(user,usuarios.getRaiz()));
		else {
			NodoABB nuevo = new NodoABB(user);
			usuarios.setRaiz(nuevo);
		}
	}
	private NodoABB agregarUsuario(Usuario usr, NodoABB abb){
		if (abb==null)
			abb= new NodoABB(usr);
		else if (abb.getUsuario().getUsuarioID().compareTo(usr.getUsuarioID())==-1){ // si es menor
			abb.setDer(agregarUsuario(usr, abb.getDer()));
		}else{
			abb.setIzq(agregarUsuario(usr, abb.getIzq()));

		}
		return abb;
	}

	public Usuario buscarUsuario(String Id, NodoABB abb){
		if(abb!=null){
			if(abb.getUsuario().getUsuarioID().compareTo(Id)==0)// si es igual
				return abb.getUsuario();
			else if (abb.getUsuario().getUsuarioID().compareTo(Id)==-1)// si es menor
				return buscarUsuario(Id, abb.getDer());
			else 
				return buscarUsuario(Id, abb.getIzq());
		}else
			return null;
	}

	public void cambiarEstado(Usuario usr){
		usr.setEstado(2);
	}

	private boolean existeUsuario(String Id, NodoABB abb){
		if(abb != null){
			if(abb.getUsuario().getUsuarioID() == Id)
				return true;
			else if(abb.getUsuario().getUsuarioID().compareTo(Id)==-1)// si es menor
				return existeUsuario(Id, abb.getDer());
			else
				return existeUsuario(Id, abb.getIzq());
		}else
			return false;

	}

	public TipoRet solicitarAmistad(String UsuarioO,String UsuarioD){
		if (!UsuarioO.equalsIgnoreCase(UsuarioD)){
			Usuario usuO=buscarUsuario(UsuarioO,this.usuarios.getRaiz());
			if ((usuO!=null)&&(usuO.getEstado()==1)){
				Usuario usuD=buscarUsuario(UsuarioD,this.usuarios.getRaiz());
				if ((usuD!=null)&&(usuD.getEstado()==1)){
					if(!sonamigos( UsuarioO, UsuarioD)){//sino son amigos OK
						return enviarMensajeSolicitudAmistad(UsuarioO, UsuarioD, "Nueva solicitud de amistad", "El usuario "+ UsuarioO +"le solicita que sea su amigo");
					}else{
						return TipoRet.OK;
					}

				}else{
					System.out.println("El usuario "+ UsuarioD +"  no existe");
					return TipoRet.ERROR;
				}
			}else{
				System.out.println("El usuario "+ UsuarioO +  "  no existe");
				return TipoRet.ERROR;

			}

		}
		System.out.println("Usuario origen y usuario destino deben ser diferentes");
		return TipoRet.ERROR;
	}


	TipoRet enviarMensajeSolicitudAmistad(String usuarioO, String usuarioD, String asunto, String mensaje){

		if (existeUsuario(usuarioO,usuarios.getRaiz())){
			if (existeUsuario(usuarioD,usuarios.getRaiz())){
				Usuario usuD=buscarUsuario(usuarioD, usuarios.getRaiz());
				//usuD.getMensajes().push(usuarioO, asunto, mensaje);
				usuD.getSolicitudAmistad().push(usuarioO, asunto, mensaje);
				usuD.setCantSolicitudesPend(usuD.getCantSolicitudesPend()+1); // incremento contador cantidad de solicitudes.
				return TipoRet.OK;
			}
			else{
				System.out.println("El usuario "+ usuarioD + "no existe.");
				return TipoRet.ERROR;
			}	
		}else{
			System.out.println("El usuario "+ usuarioO + "no existe.");
			return TipoRet.ERROR;
		}
	}
	TipoRet enviarMensaje(String usuarioO, String usuarioD, String asunto, String mensaje){

		if (existeUsuario(usuarioO,usuarios.getRaiz())){
			if (existeUsuario(usuarioD,usuarios.getRaiz())){
				if(sonamigos(usuarioO, usuarioD)){
					Usuario usuD=buscarUsuario(usuarioD, usuarios.getRaiz());
					usuD.getMensajes().push(usuarioO, asunto, mensaje);
					
										
					usuD.setCantMensajesRec(usuD.getCantMensajesRec()+1); // incremento contador cantidad de mensajes recibidos en el usuario destino
					
					Usuario usuO=buscarUsuario(usuarioO, usuarios.getRaiz());
					
					usuO.setCantMensajesEnv(usuO.getCantMensajesEnv()+1); // incremento contador cantidad de mensajes enviados en el usuario origen.
					
					return TipoRet.OK;
				}
				else{
					System.out.println("El usuario "+ usuarioO + "  y el usuario "+ usuarioD +"  no son amigos.");
					return TipoRet.ERROR;
				}
			}
			else{
				System.out.println("El usuario "+ usuarioD + "  no existe.");
				return TipoRet.ERROR;
			}	
		}else{
			System.out.println("El usuario "+ usuarioO + "  no existe.");
			return TipoRet.ERROR;
		}

	}

	public boolean sonamigos(String usuO,String usuD){

		Usuario usuarioO= buscarUsuario(usuO,usuarios.getRaiz());
		if(usuarioO.buscarAmigo(usuD)){
			Usuario usuarioD= buscarUsuario(usuD,usuarios.getRaiz());
			if (usuarioD.buscarAmigo(usuO)){
				return true;
			}
		}
		return false;
	} 

	TipoRet listarEventosPendientes(String usuarioID){
		Usuario usu=buscarUsuario(usuarioID,usuarios.getRaiz());
		if((usu!=null)&&(usu.getEstado()==1)){		
			if (!usu.getInvitacionesEventos().esVacia()){
				System.out.println("Mensajes de "+ usuarioID);
				listarEventosPendientes(usu.getInvitacionesEventos().getInicio());
			}else{
				System.out.println("No hay invitaciones pendientes");
			}
		}else{
			System.out.println("El usuario "+ usuarioID + "no existe.");
			return TipoRet.ERROR;
		}
		return TipoRet.OK;
	}
	private void listarEventosPendientes(NodoListaInvitacionesEventos Nodo){
		System.out.println("\n Nombre Evento:" +Nodo.getNombreEvento() + "\n");
		System.out.println("\t Anfitrion: "+Nodo.getUsr()+ "\n");
		System.out.println("\t Fecha: "+Nodo.getFechaEvento()+ "\n");
		System.out.println("\t Hora: "+Nodo.getHoraEvento()+ "\n");
		if (Nodo.getSig()!=null){
			listarEventosPendientes(Nodo.getSig());
		}
	}

	/*ESTABAN EN  SISTEMA */

	TipoRet registrarUsuario(String usuarioID){

		if(existeUsuario(usuarioID, getUsuarios().getRaiz())){
			System.out.println("Ya existe el usuario " + usuarioID);
			return TipoRet.ERROR;
		}
		Usuario u=new Usuario(usuarioID);
		agregarUsuario(u);
		return TipoRet.OK;


	}

	TipoRet eliminarUsuario(String usuarioID){
		Usuario usr=buscarUsuario(usuarioID, getUsuarios().getRaiz());
		if (usr==null){
			System.out.println("No existe usuario"+ usuarioID);
			return TipoRet.ERROR;
		}else if (usr.getEstado()==2){ // si esta inactivo
			System.out.println("El usuario"+ usuarioID+ " ya esta inactivo");
			return TipoRet.ERROR;
		}else{
			cambiarEstado(usr); //se cambia estado a inactivo
			return TipoRet.OK;
		}

	}


	TipoRet responderSolicitudAmistad(String usuarioID, RespuestaAmistad resp){
		Usuario usuarioOrigen=null;

		if(resp != RespuestaAmistad.ACEPTAR){
			Usuario usr=buscarUsuario(usuarioID, getUsuarios().getRaiz());
			if (usr!=null){
				usr.getSolicitudAmistad().pop();
				usr.setCantSolicitudesPend((usr.getCantSolicitudesPend()-1)); //decremento el contador luego de hacer POP.
				return TipoRet.OK; //si respuesta no es aceptar  lo borro y retorno ok pero no hago nada.
			}else{
				System.out.println("El usuario "+  usuarioID + "  No existe");
				return TipoRet.ERROR;
			}
		}
		Usuario usr=buscarUsuario(usuarioID, getUsuarios().getRaiz());
		if(usr==null){
			System.out.println("El usuario"+ usuarioID+ "  No existe");
			return TipoRet.ERROR;
		}else if (usr.getEstado()==2){// inactivo
			System.out.println("El usuario"+ usuarioID + "  No existe"); // asi pide la letra q si esta inactivo devuelvo q no existe.
			return TipoRet.ERROR;
		}else {
			NodoPilaSolicitudes aux=usr.getSolicitudAmistad().getInicio();
			usuarioOrigen =buscarUsuario(aux.getUsuarioID(), getUsuarios().getRaiz());
		}

		if ((usuarioOrigen==null)||(usuarioOrigen.getEstado()==2)){
			// si el usuarioOrigen esta inactivo devuelvo ok luego de sacar la solicitud de la Pila
			usr.setCantSolicitudesPend((usr.getCantSolicitudesPend()-1)); //decremento el contador luego de hacer POP.
			usr.getSolicitudAmistad().pop();
			return TipoRet.OK; 
		}else{

			usr.agregarAlistaDeAmigos(usuarioOrigen);
			usuarioOrigen.agregarAlistaDeAmigos(usr);
			usr.setCantSolicitudesPend((usr.getCantSolicitudesPend()-1));
			usr.getSolicitudAmistad().pop();
			enviarMensaje(usr.getUsuarioID(), usuarioOrigen.getUsuarioID(), "Han aceptado su solicitud de amistad", "Ahora usuarioID es su amigo");
			return TipoRet.OK;
		}

	}



	/*Retorno enviarMensaje(String usuarioO, String usuarioD, String asunto, String mensaje){

		if(existeUsuario(usuarioO,getUsuarios().getRaiz())){
			if(existeUsuario(usuarioO,getUsuarios().getRaiz())){

				if  (sonamigos(usuarioO,usuarioD)){
					Usuario usuD=buscarUsuario(usuarioD,getUsuarios().getRaiz());
					Usuario usuO=buscarUsuario(usuarioO,getUsuarios().getRaiz());//traigo el otro usuario para aumentar contador
					usuD.getMensajes().push(usuarioO, asunto, mensaje);
					usuD.setCantMensajesRec(usuD.getCantMensajesRec()+1);//incremento mensajes recibidos en el que recibe el msg.
					usuO.setCantMensajesEnv(usuD.getCantMensajesEnv()+1); //incremento mensajes enviados en el usuario que envia
					return Retorno.OK;
				}else {
					System.out.println("El usuario " + usuarioO + " y el " + usuarioD + "no son amigos");
					return Retorno.ERROR;
				}
			}else{
				System.out.println("El usuario " + usuarioD + " no existe");
				return Retorno.ERROR;
			}
		}else{
			System.out.println(" El usuario " + usuarioO + " no existe");
			return Retorno.ERROR;
		}
	}*/



	TipoRet leerBandejaEntrada (String usuarioID){

		if(existeUsuario(usuarioID, getUsuarios().getRaiz())){
			Usuario usu=buscarUsuario(usuarioID,getUsuarios().getRaiz());
			if (usu.getEstado()==2){
				System.out.println("El usuario " + usuarioID + " no existe");
				return TipoRet.ERROR;
			}
			System.out.println("Mensajes del usuario " + usuarioID);
			System.out.println (usu.getMensajes().mostrarPila());
			return TipoRet.OK;
		}else{
			System.out.println("El usuario "+ usuarioID + " no existe");
			return TipoRet.ERROR;
		}

	}








	TipoRet invitarEvento(String usuarioO, String usuarioD, String nombreEvento, int fechaEvento, int horaEvento){

		if (fechaEvento<1 || fechaEvento>365){
			System.out.println("Fecha no Valida");
			return TipoRet.ERROR;
		}
		if (horaEvento<0 || horaEvento>24){
			System.out.println("Hora no Valida");
			return TipoRet.ERROR;
		}
		if(usuarioO.equalsIgnoreCase(usuarioD)){
			System.out.println("Usuario origen y destino deben ser diferentes");
			return TipoRet.ERROR;
		}
		
		Usuario usuD=buscarUsuario(usuarioD,getUsuarios().getRaiz());
		Usuario usuO=buscarUsuario(usuarioO,getUsuarios().getRaiz());
		if (usuD==null){
			System.out.println("El usuario " + usuarioD + " no existe");
			return TipoRet.ERROR;
		}
		if (usuO==null){
			System.out.println("El usuario " + usuarioO + " no existe");
			return TipoRet.ERROR;
		}
		if  (!sonamigos(usuarioO,usuarioD)){
			System.out.println("Los usuarios " + usuarioO + " y " + usuarioD + " no son amigos");	
			return TipoRet.ERROR;
		}
		usuD.agregarEvento(usuarioO, nombreEvento, fechaEvento, horaEvento);
		usuD.setCantEventosPend(usuD.getCantEventosPend()+1);
		return TipoRet.OK;	
	}

	public TipoRet destruiRed(){
		usuarios.setRaiz(eliminarArbol(usuarios.getRaiz()));
		return TipoRet.OK;
	}
	private NodoABB eliminarArbol(NodoABB nodo){

		if(nodo.getIzq()!=null){
			nodo.setIzq(eliminarArbol( nodo.getIzq()));			
		}
		else if(nodo.getDer()!=null){
			nodo.setDer(eliminarArbol( nodo.getDer()));
		}
		if((nodo.getIzq()==null)&&(nodo.getDer()==null)){
			if(nodo.getUsuario()!=null){
				nodo.getUsuario().destruirUsuario();
				nodo.setUsuario(null);
			}
			nodo=null;
		}
		return nodo;
	}	



}
